package com.eastedu.service;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.eastedu.client.encrypt.FileDecryptClient;
import com.eastedu.client.encrypt.FileEncryptClient;
import com.eastedu.client.encrypt.FileHlsEncryptClient;
import com.eastedu.client.encrypt.model.FileEncryptRequest;
import com.eastedu.converter.BasicResourceFileConverter;
import com.eastedu.exception.ServiceException;
import com.eastedu.repository.basic.mapper.BasicResourceFileMapper;
import com.eastedu.repository.basic.po.BasicResourceFilePO;
import com.eastedu.repository.basic.po.BasicResourcePO;
import com.eastedu.superise.CustomDataClassRowMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.sql.SQLException;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

/**
 * 处理历史mp4文件加密
 *
 * @author zhangzhishuai
 */
@Slf4j
@Service
public class FileEncryptDataService {

    private final BasicResourceFileMapper basicResourceFileMapper;
    private final BasicResourceFileConverter basicResourceFileConverter;
    private final FileDecryptClient fileDecryptClient;
    private final FileHlsEncryptClient fileHlsEncryptClient;
    private final JdbcTemplate jdbcTemplate;
    private final FileEncryptClient fileEncryptClient;
    private final AtomicLong total;

    public FileEncryptDataService(BasicResourceFileMapper basicResourceFileMapper, BasicResourceFileConverter basicResourceFileConverter, FileDecryptClient fileDecryptClient, FileHlsEncryptClient fileHlsEncryptClient, JdbcTemplate jdbcTemplate, FileEncryptClient fileEncryptClient) {
        this.basicResourceFileMapper = basicResourceFileMapper;
        this.basicResourceFileConverter = basicResourceFileConverter;
        this.fileDecryptClient = fileDecryptClient;
        this.fileHlsEncryptClient = fileHlsEncryptClient;
        this.jdbcTemplate = jdbcTemplate;
        this.fileEncryptClient = fileEncryptClient;
        this.total = new AtomicLong(0);
    }


    /**
     * 加密范围 幼儿园和其他
     * @return sql
     */
    private String getSql() {
        return "SELECT * FROM (\n" + sql() + ") a LIMIT 2";

    }

    protected String sql() {
        return """
                SELECT
                \tr.*\s
                FROM
                \tt_basic_resource r
                \tINNER JOIN t_basic_resource_file f on f.basic_resource_id = r.id
                WHERE
                \tr.study_section_code IN ( 'GZ', 'CZ', 'XX' )\s
                \tAND r.category IN ( 1, 7, 8, 9, 10, 30, 32 )\s
                \tAND r.create_time > 1577808000000\s
                \tAND r.encrypt_state IS NULL\s
                \tAND r.source_app_code NOT IN ( 'U-learning-Course-Service' )\s
                \tand f.extension = 'mp4'
                \t union\s
                \tSELECT
                \tr.*\s
                FROM
                \tt_basic_resource r
                \tINNER JOIN t_basic_resource_file f on f.basic_resource_id = r.id
                WHERE
                \tr.study_section_code IN ('XQ')\s
                \tAND r.category IN ( 1, 7, 8, 9, 10, 30, 32 )\s
                \tAND r.encrypt_state IS NULL\s
                \tAND r.source_app_code NOT IN ( 'U-learning-Course-Service' )\s
                \tand f.extension = 'mp4'
                """;
    }
    private String getCountSql() {
        return "SELECT count(1) FROM (" + sql() + ") a";

    }

    public void encrypt() {
        //    @Scheduled(cron = "0/10 * * * * ?")
        log.info("定时任务持续运行中......");
        List<BasicResourcePO> resources = jdbcTemplate.query(getSql(), new CustomDataClassRowMapper<>(BasicResourcePO.class));
        if (CollectionUtils.isEmpty(resources)) {
            log.info("任务同步完成！");
            return;
        }
        // 生成 0-50 中的一个随机数
        resources.forEach(resource -> {
            try {
                this.callback(resource);
            } catch (SQLException e) {
                log.error("执行出错：", e);
            }
            log.info("剩余数据量： {}", total.decrementAndGet());
        });
    }

    public void callback(BasicResourcePO po) throws SQLException {
        if (Objects.nonNull(po.getEncryptState())) {
            return;
        }
        List<BasicResourceFilePO> basicResourceFilePoList = this.basicResourceFileMapper
                .selectList(Wrappers.lambdaQuery(BasicResourceFilePO.class)
                        .eq(BasicResourceFilePO::getBasicResourceId, po.getId()));
        List<Long> fileIds = basicResourceFilePoList.stream().filter(o -> "mp4".equalsIgnoreCase(o.getExtension()))
                .map(BasicResourceFilePO::getFileId).map(Long::valueOf).distinct().collect(Collectors.toList());
        log.info("文件ID处理中{}", fileIds);
        this.mp4HlsFileEncrypt(fileIds);
///        this.mp4FileEncrypt(String.valueOf(po.getId()), fileIds);
    }

    private void mp4HlsFileEncrypt(List<Long> fileIds) {
        fileIds.forEach(this.fileHlsEncryptClient::retryMqFileEncrypt);
    }


    private List<Long> mp4FileEncrypt(String baseResourceId, List<Long> fileIds) {
        FileEncryptRequest fileEncryptRequest = basicResourceFileConverter.toFileEncryptRequest(baseResourceId, fileIds);
        try {
            return fileDecryptClient.createFileEncrypt(fileEncryptRequest);
        } catch (Exception e) {
            log.error("调用解密服务加密失败：", e);
            throw new ServiceException("调用解密服务加密失败：" + e.getMessage());
        }
    }

}
